package com.ysjy.course.aop;

import com.alibaba.fastjson.JSONObject;
import com.ysjy.course.exception.MyException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 给所有service服务增加打印日志
 *
 */
@Component
@Aspect
@Slf4j
public class ControllerLogAop {

    /**
     * 定义一个切片
     */
    @Pointcut("execution(public * com.ysjy.course.controller..*.*(..))")
    private void controllerMethod() {

    }



    /**
     * 增加try catch
     *
     * @param pjp
     *
     * @return
     */
    @Around("controllerMethod()")
    public Object addTryCatch(ProceedingJoinPoint pjp) throws Throwable {
        try {
            long start = System.currentTimeMillis();
            Object result = pjp.proceed();

            long last = System.currentTimeMillis() - start;
            printLog(pjp, result, last);
            return result;
        } catch (Exception e) {
            printExceptionLog(pjp);
            if(!(e instanceof MyException)){
                log.error("controller方法拦截日志打印错误", e);
                throw e;
            }
            throw e;
        }
    }


    /**
     * 打印拦截信息
     *
     * @param pjp          信息
     * @param returnObject 返回结果
     * @param last         持续时间
     */
    private void printLog(ProceedingJoinPoint pjp, Object returnObject, long last) {
        String className = pjp.getTarget().getClass().toString();
        String methodName = pjp.getSignature().getName();
        Object[] args = pjp.getArgs();
        StringBuffer sb = new StringBuffer();
        for (Object o : args) {
            sb.append(o + ", ");
        }

        String params = sb.toString();
        if(params.length()>200)
        {
            params = params.substring(0,200);
        }
        if (methodName.startsWith("get") || methodName.startsWith("query") || methodName.startsWith("find")) {
            log.info(" [类名]=" + className + " [方法名]=" + methodName + " [持续时间]=" + last + " [参数]=" + params);
        } else {
            String returnObjectStr = JSONObject.toJSONString(returnObject);
            if(returnObjectStr.length()>200)
            {
                returnObjectStr = returnObjectStr.substring(0,200);
            }
            log.info(" [类名]=" + className + " [方法名]=" + methodName + " [持续时间]=" + last + " [参数]=" + params + " [返回]=" + returnObjectStr);
        }
    }

    private void printExceptionLog(ProceedingJoinPoint pjp) {
        String className = pjp.getTarget().getClass().toString();
        String methodName = pjp.getSignature().getName();
        Object[] args = pjp.getArgs();
        StringBuffer params = new StringBuffer();
        for (Object o : args) {
            params.append(o + ", ");
        }
        log.info(" [异常类名]=" + className + " [异常方法名]=" + methodName + " [异常参数]=" + params.toString());
    }
}
